package engine.systems.input.interaction
{
	import ash.core.Component;
	import ash.core.Entity;
	
	import flash.display.DisplayObjectContainer;
	import flash.events.Event;
	import flash.events.MouseEvent;
	
	import org.osflash.signals.Signal;
	import org.osflash.signals.natives.NativeSignal;

	public class Interaction extends Component
	{
		public static const CLICK:String 	= "click";
		public static const UP:String 		= "up";
		public static const DOWN:String 	= "down";
		public static const OVER:String 	= "over";
		public static const OUT:String 		= "out";
		//public static const RELEASE:String	= "release";
		public static const TYPES:Array		= [CLICK, UP, DOWN, OVER, OUT];
		
		public var locked:Boolean;
		
		public var click:Signal 	= new Signal(Entity, MouseEvent);
		public var up:Signal 		= new Signal(Entity, MouseEvent);
		public var down:Signal 		= new Signal(Entity, MouseEvent);
		public var over:Signal 		= new Signal(Entity, MouseEvent);
		public var out:Signal 		= new Signal(Entity, MouseEvent);
		//public var release:Signal	= new Signal(Entity, MouseEvent);
		
		internal var _clickNative:NativeSignal;
		internal var _upNative:NativeSignal;
		internal var _downNative:NativeSignal;
		internal var _overNative:NativeSignal;
		internal var _outNative:NativeSignal;
		//internal var _releaseNative:NativeSignal;
		
		internal var _clickEvent:MouseEvent;
		internal var _upEvent:MouseEvent;
		internal var _downEvent:MouseEvent;
		internal var _overEvent:MouseEvent;
		internal var _outEvent:MouseEvent;
		//internal var _releaseEvent:MouseEvent;
		
		internal var _clickActive:Boolean 	= false;
		internal var _upActive:Boolean 		= false;
		internal var _downActive:Boolean 	= false;
		internal var _overActive:Boolean 	= false;
		internal var _outActive:Boolean 	= false;
		//internal var _releaseActive:Boolean = false;
		
		internal var _clickActivate:Boolean 	= false;
		internal var _upActivate:Boolean 		= false;
		internal var _downActivate:Boolean 		= false;
		internal var _overActivate:Boolean 		= false;
		internal var _outActivate:Boolean 		= false;
		//internal var _releaseActivate:Boolean 	= false;
		
		internal var _invalidate:Boolean = false;
		
		internal var _interactions:Array 			= [];
		internal var _updateInteractions:Boolean 	= false;
		
		public function Interaction(interactions:Array = null, locked:Boolean = false)
		{
			this.interactions 	= interactions;
			this.locked 		= locked;
		}
		
		override public function destroy():void
		{
			this.click.removeAll();		this.click 	= null;
			this.up.removeAll();		this.up 	= null;
			this.down.removeAll();		this.down 	= null;
			this.over.removeAll();		this.over 	= null;
			this.out.removeAll();		this.out 	= null;
			//this.release.removeAll();	this.release = null;
			
			if(this._clickNative) 	{ this._clickNative.removeAll(); 	this._clickNative 	= null; }
			if(this._upNative) 		{ this._upNative.removeAll(); 		this._upNative 		= null; }
			if(this._downNative) 	{ this._downNative.removeAll(); 	this._downNative 	= null; }
			if(this._overNative) 	{ this._overNative.removeAll(); 	this._overNative 	= null; }
			if(this._outNative) 	{ this._outNative.removeAll(); 		this._outNative 	= null; }
			//if(this._releaseNative)	{ this._releaseNative.removeAll();	this._releaseNative = null; }
			
			this._clickEvent 	= null;
			this._upEvent 		= null;
			this._downEvent 	= null;
			this._overEvent		= null;
			this._outEvent 		= null;
			//this._releaseEvent 	= null;
			
			this._interactions 	= null;
		}
		
		public function get interactions():Array { return this._interactions.slice(); }
		public function set interactions(interactions:Array):void
		{
			if(!interactions) this._interactions = Interaction.TYPES.slice();
			else this._interactions = interactions.slice();
			
			this._updateInteractions = true;
		}
		
		internal function clickHandler(event:MouseEvent):void
		{
			if(this.locked) return;
			
			this._invalidate 		= true;
			this._clickActivate 	= true;
			this._clickEvent 		= event;
		}
		
		internal function upHandler(event:MouseEvent):void
		{
			if(this.locked) return;
			
			this._invalidate 		= true;
			this._upActivate 		= true;
			this._upEvent			= event;
		}
		
		internal function downHandler(event:MouseEvent):void
		{
			if(this.locked) return;
			
			this._invalidate 		= true;
			this._downActivate 		= true;
			this._downEvent			= event;
		}
		
		internal function overHandler(event:MouseEvent):void
		{
			if(this.locked) return;
			
			this._invalidate 		= true;
			this._overActivate 		= true;
			this._overEvent			= event;
		}
		
		internal function outHandler(event:MouseEvent):void
		{
			if(this.locked) return;
			
			this._invalidate 		= true;
			this._outActivate 		= true;
			this._outEvent			= event;
		}
		
		internal function displayChanged(entity:Entity):void
		{
			this._updateInteractions = true;
		}
		
		/*internal function releaseHandler(event:MouseEvent):void
		{
			if(this._locked) return;
			
			this._invalidate 		= true;
			this._releaseActivate 	= true;
			this._releaseEvent		= event;
		}*/
		
		public static function createNativeSignal(display:DisplayObjectContainer, interaction:String):NativeSignal
		{
			var native:NativeSignal;
			
			switch(interaction)
			{
				case Interaction.CLICK:
					native = new NativeSignal(display, MouseEvent.CLICK, 		MouseEvent);
					break;
				case Interaction.UP:
					native = new NativeSignal(display, MouseEvent.MOUSE_UP, 	MouseEvent);
					break;
				case Interaction.DOWN:
					native = new NativeSignal(display, MouseEvent.MOUSE_DOWN, 	MouseEvent);
					break;
				case Interaction.OVER:
					native = new NativeSignal(display, MouseEvent.MOUSE_OVER, 	MouseEvent);
					break;
				case Interaction.OUT:
					native = new NativeSignal(display, MouseEvent.MOUSE_OUT, 	MouseEvent);
					break;
				//case Interaction.RELEASE:
					//native = new NativeSignal(display, "releaseOutside", 		MouseEvent);
					//break;
				default:
					throw new Error("Interaction :: createNativeSignal() :: Interaction <" + interaction + "> is an invalid value!")
					break;
			}
			
			return native;
		}
	}
}